package com.quwan.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.quwan.app.service.MemberDynamicService;
import com.quwan.app.service.MemberService;
import com.quwan.app.vo.*;
import com.quwan.common.BaseService;
import com.quwan.common.Check;
import com.quwan.common.enums.CommonStatus;
import com.quwan.common.enums.MemberStatusEnum;
import com.quwan.common.enums.SystemMsgEnum;
import com.quwan.common.exception.ExpCode;
import com.quwan.common.exception.ResponseException;
import com.quwan.common.result.PageResult;
import com.quwan.component.AsyncTaskComponent;
import com.quwan.config.yml.ImConfig;
import com.quwan.config.yml.OssConfig;
import com.quwan.entity.*;
import com.quwan.mapper.*;
import com.quwan.utils.DateUtils;
import com.quwan.utils.Parse;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author quan
 * @date 2021-07-24 10:29
 */

@Service
@RequiredArgsConstructor
public class MemberDynamicServiceImpl extends BaseService implements MemberDynamicService {
    private final TMemberDynamicMapper memberDynamicMapper;
    private final TMemberDynamicFileMapper dynamicFileMapper;
    private final TDynamicCommentMapper dynamicCommentMapper;
    private final TDynamicFollowMapper dynamicFollowMapper;
    private final TMemberMapper memberMapper;
    private final OssConfig ossConfig;
    private final MemberService memberService;
    private final TCommentFollowMapper commentFollowMapper;
    private final AsyncTaskComponent taskComponent;
    private final ImConfig imConfig;
    @Value("${msg.dynamicFollow}")
    private String dynamicFollow;
    @Value("${msg.dynamicComment}")
    private String dynamicComment;

    @Override
    public PageResult<MemberDynamicDTO> getMemberDynamicList(int pageNo, int pageSize, String mId, String status, String type) {
        //当前登录用户 可以null
        String currMember = mId;
        Page<Map> result =
                memberDynamicMapper
                        .selectMemberDynamicList(
                                new Page<>(pageNo, pageSize), mId, status, type, currMember);

        return new PageResult<MemberDynamicDTO>()
                .setSize(result.getSize())
                .setTotal(result.getTotal())
                .setPages(result.getPages())
                .setCurrent(result.getCurrent())
                .setRecords(
                        result.getRecords()
                                .stream()
                                .map(m -> {
                                    MemberDynamicDTO dto = new MemberDynamicDTO();
                                    String imgs = (String) m.get("imgs");
                                    dto
                                            .setMember(
                                                    new MemberShowInfo()
                                                            .setImgUrl(ossConfig.getHostname() + "/" + String.valueOf(m.get("img_url")))
                                                            .setNickName(String.valueOf(m.get("nick_name")))
                                                            .setMId(String.valueOf(m.get("mId")))
                                                            .setArea(parseArea(String.valueOf(m.get("area"))))
                                                            .setServiceLevel(Integer.parseInt(m.get("service_level") == null ? "0" : String.valueOf(m.get("service_level")))))
                                            .setItem(StringUtils.isBlank(imgs) ? new ArrayList<>() :
                                                    Arrays.asList(imgs.split(","))
                                                            .stream()
                                                            .filter(StringUtils::isNotBlank)
                                                            .map(url -> new TMemberDynamicFile().setUrl(ossConfig.getHostname() + "/" + url))
                                                            .collect(Collectors.toList()))
                                            .setDianzan(!"0".equals(String.valueOf(m.get("dianzan"))))
                                            .setVip(Parse.toInt(m.get("vip"), 0) > 0)
                                            .setFollower(!"0".equals(String.valueOf(m.get("follower"))))
                                            .setComment(Integer.parseInt(String.valueOf(m.get("comment"))))
                                            .setFollow(Integer.parseInt(String.valueOf(m.get("follow"))))
                                            .setTitle(String.valueOf(m.get("title")))
                                            .setAddTime(DateUtils.parseDate(m.get("add_time")))
                                            .setId(Long.parseLong(String.valueOf(m.get("id"))));
                                    return dto;

                                })
                                .collect(Collectors.toList())
                );
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    @Override
    public boolean addDynamicFollow(String mId, String dynamicId) {
        if (dynamicFollowMapper
                .update(null,
                        new LambdaUpdateWrapper<TDynamicFollow>()
                                .set(TDynamicFollow::getStatus, CommonStatus.NORMAL.getType())
                                .eq(TDynamicFollow::getMId, mId)
                                .eq(TDynamicFollow::getDynamicId, dynamicId)) == 1)
            return true;
        else {
            TDynamicFollow tDynamicFollow = new TDynamicFollow()
                    .setDynamicId(Long.parseLong(dynamicId))
                    .setMId(Long.parseLong(mId));
            int row = dynamicFollowMapper
                    .insert(tDynamicFollow);
            if (row == 1) {
                //进行广场消息推送
                TMemberDynamic dynamic = memberDynamicMapper.selectOne(new LambdaQueryWrapper<TMemberDynamic>()
                        .select(TMemberDynamic::getMId)
                        .eq(TMemberDynamic::getId, dynamicId)
                        .eq(TMemberDynamic::getStatus, CommonStatus.NORMAL.getType()));

                if (dynamic != null) {
                    TMember member = memberMapper.selectOne(new LambdaQueryWrapper<TMember>()
                            .select(TMember::getEnableDynamic)
                            .eq(TMember::getId, dynamic.getMId())
                            .eq(TMember::getStatus, MemberStatusEnum.NORMAL.getCode()));

                    if (member != null && CommonStatus.NORMAL.getType().equals(member.getEnableDynamic())) {
                        InteractiveMsgParams params =
                                new InteractiveMsgParams()
                                        .setFromAcc(imConfig.getDynamicAcc())
                                        .setToAcc(dynamic.getMId().toString())
                                        .setContent(dynamicFollow)
                                        .setType(SystemMsgEnum.DYNAMIC.getType() * -1)
                                        .setMId(mId)
                                        .setId(dynamicId);
                        taskComponent.pushInteractiveMsg(params);
                    }
                }
                return true;
            }
            return false;

        }

    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    @Override
    public boolean cancelDynamicFollow(String mId, String dynamicId) {
        return dynamicFollowMapper
                .update(null,
                        new LambdaUpdateWrapper<TDynamicFollow>()
                                .set(TDynamicFollow::getStatus, CommonStatus.DISABLED.getType())
                                .eq(TDynamicFollow::getMId, mId)
                                .eq(TDynamicFollow::getDynamicId, dynamicId)
                ) == 1;
    }

    @Override
    public PageResult<TDynamicComment> getDynamicList(int pageNo, int pageSize, String dynamicId, String mId) {
        Page<TDynamicComment> page =
                dynamicCommentMapper.
                        selectPage(new Page<>(pageNo, pageSize),
                                new LambdaQueryWrapper<TDynamicComment>()
                                        .select(TDynamicComment::getMessage, TDynamicComment::getId, TDynamicComment::getMId, TDynamicComment::getDynamicId, TDynamicComment::getReply,
                                                TDynamicComment::getAddTime)
                                        .eq(TDynamicComment::getDynamicId, dynamicId)
                                        .orderByAsc(TDynamicComment::getAddTime));

        if (CollectionUtils.isEmpty(page.getRecords()))
            return new PageResult<>();
        ImmutableMap<Long, TMember> memberMaps =
                Maps
                        .uniqueIndex(
                                memberMapper
                                        .selectList(
                                                new LambdaQueryWrapper<TMember>()
                                                        .select(TMember::getId, TMember::getNickName, TMember::getImgUrl)
                                                        .in(TMember::getId, page
                                                                .getRecords()
                                                                .stream()
                                                                .map(TDynamicComment::getMId)
                                                                .collect(Collectors.toList()))),
                                TMember::getId);
        String ids = page.getRecords().stream().map(m -> m.getId() + "").collect(Collectors.joining(","));
        ids = StringUtils.isBlank(ids) ? "-1" : ids;
        Map<String, CommentFollow> count = dynamicCommentMapper.selectFollowCountById(ids)
                .stream()
                .collect(Collectors.toMap(CommentFollow::getCommentId, f -> f));
        String unLocks = page.getRecords().stream().map(m -> mId + m.getId()).collect(Collectors.joining(","));
        unLocks = StringUtils.isBlank(unLocks) ? "-1" : unLocks;
        Map<String, CommentFollow> dianzan = dynamicCommentMapper.selectMemberFollowComment(unLocks)
                .stream()
                .collect(Collectors.toMap(CommentFollow::getCommentId, f -> f));
        return new PageResult<TDynamicComment>()
                .setSize(page.getSize())
                .setTotal(page.getTotal())
                .setPages(page.getPages())
                .setCurrent(page.getCurrent())
                .setRecords(
                        page
                                .getRecords()
                                .stream()
                                .map(m ->
                                        {
                                            CommentFollow follow = count.get(String.valueOf(m.getId()));
                                            CommentFollow zan = dianzan.get(String.valueOf(m.getId()));
                                            m.setCommentMember(memberMaps.get(m.getMId()) == null ? "" :
                                                    memberMaps.get(m.getMId()).getNickName())
                                                    .setMemberHead(memberMaps.get(m.getMId()) == null ? "" :
                                                            ossConfig.getHostname() + "/" + memberMaps.get(m.getMId()).getImgUrl())
                                                    .setFollow(follow == null ? 0 : follow.getC())
                                                    .setDianzan(zan != null && zan.getC() != 0)
                                            ;
                                            return m;
                                        }
                                )
                                .collect(Collectors.toList())
                );
    }

    @Override
    public boolean publishDynamic(String mId, String title, String topic, String files) {
        TMemberDynamic memberDynamic =
                new TMemberDynamic()
                        .setTitle(title)
                        .setMId(Long.parseLong(mId))
                        .setTopic(topic);
        int row = memberDynamicMapper.insert(memberDynamic);

        if (StringUtils.isBlank(files)) return row == 1;
        if (files.contains("，")) files = files.replace("，", ",");
        String[] urls = files.split(",");
        List<TMemberDynamicFile> items = Arrays
                .stream(urls)
                .map(url ->
                        new TMemberDynamicFile()
                                .setUrl(url.trim().replace(ossConfig.getHostname() + "/", ""))
                                .setDynamicId(memberDynamic.getId())
                                .setAddTime(new Date()).setType(CommonStatus.NORMAL.getType()).setMId(0L)

                ).collect(Collectors.toList());
        Integer itemRow = dynamicFileMapper.insertBatchSomeColumn(items);
        return urls.length == itemRow && row == 1;
    }

    @Override
    public boolean addDynamicComment(String dynamicId, String mId, String message) {
        TDynamicComment dynamicComment = new TDynamicComment()
                .setMessage(message)
                .setMId(Long.parseLong(mId))
                .setDynamicId(Long.parseLong(dynamicId));

        boolean success = dynamicCommentMapper.insert(dynamicComment) == 1;

        if (success) {
            //进行广场消息推送
            TMemberDynamic dynamic = memberDynamicMapper.selectOne(new LambdaQueryWrapper<TMemberDynamic>()
                    .select(TMemberDynamic::getMId)
                    .eq(TMemberDynamic::getId, dynamicId)
                    .eq(TMemberDynamic::getStatus, CommonStatus.NORMAL.getType()));

            if (dynamic != null) {
                TMember member = memberMapper.selectOne(new LambdaQueryWrapper<TMember>()
                        .select(TMember::getEnableDynamic)
                        .eq(TMember::getId, dynamic.getMId())
                        .eq(TMember::getStatus, MemberStatusEnum.NORMAL.getCode()));

                if (member != null && CommonStatus.NORMAL.getType().equals(member.getEnableDynamic())) {
                    InteractiveMsgParams params =
                            new InteractiveMsgParams()
                                    .setFromAcc(imConfig.getDynamicAcc())
                                    .setToAcc(dynamic.getMId().toString())
                                    .setContent(this.dynamicComment)
                                    .setType(SystemMsgEnum.DYNAMIC.getType())
                                    .setMId(mId)
                                    .setId(dynamicComment.getId().toString());
                    taskComponent.pushInteractiveMsg(params);
                }
            }
        }

        return success;
    }

    @Override
    public PageResult<MemberDynamicDTO> getMemberDynamicListById(String id, int pageNo, int pageSize, String mId) {
        Page<Map> res = memberDynamicMapper
                .selectMemberDynamicById(new Page<>(pageNo, pageSize), id, mId);
        return new PageResult<MemberDynamicDTO>()
                .setTotal(res.getTotal())
                .setCurrent(res.getTotal())
                .setPages(res.getPages())
                .setSize(res.getSize())
                .setRecords(
                        res
                                .getRecords()
                                .stream()
                                .map(m ->
                                        {
                                            MemberDynamicDTO md =
                                                    new MemberDynamicDTO()
                                                            .setDianzan(!"0".equals(String.valueOf(m.get("dianzan"))))
                                                            .setItem((String) m.get("imgs") == null ? new ArrayList<>() :
                                                                    Arrays
                                                                            .stream(((String) m.get("imgs")).split(","))
                                                                            .filter(f -> StringUtils.isNotBlank(f))
                                                                            .map(url -> new TMemberDynamicFile().setUrl(ossConfig.getHostname() + "/" + url))
                                                                            .collect(Collectors.toList()))
                                                            .setMember(new MemberShowInfo()
                                                                    .setNickName(String.valueOf(m.get("nick_name")))
                                                                    .setArea(m.get("area") == null ? "" : parseArea(String.valueOf(m.get("area"))))
                                                                    .setImgUrl(ossConfig.getHostname() + "/" + String.valueOf(m.get("img_url"))));

                                            md.setId(Long.parseLong(m.get("id").toString()))
                                                    .setTitle(String.valueOf(m.get("title")))
                                                    .setComment(Integer.parseInt(String.valueOf(m.get("comment"))))
                                                    .setFollow(Integer.parseInt(String.valueOf(m.get("follow"))))
                                                    .setTopic(String.valueOf(m.get("topic")))
                                                    .setAddTime(DateUtils.parseDate(m.get("add_time")));

                                            return md;
                                        }
                                ).collect(Collectors.toList())


                );
    }

    @Override
    public DynamicDetailsDTO getDynamicDetails(String mId, String dynamicId) {
        TMemberDynamic dynamic = memberDynamicMapper.selectOne(
                new LambdaQueryWrapper<TMemberDynamic>()
                        .eq(TMemberDynamic::getId, dynamicId)
        );
        Check.notNull(dynamic, ExpCode.DATA_SELECT_NULL);
        MemberShowInfo memberShowInfo = memberService.getMemberShowInfoById(dynamic.getMId());
        boolean isFollower = memberService.isFollowObj(mId, dynamic.getMId().toString());
        Integer dianzan = dynamicFollowMapper.selectCount(
                new QueryWrapper<>(
                        new TDynamicFollow()
                                .setDynamicId(dynamic.getId())
                                .setMId(Long.parseLong(mId))
                                .setStatus(CommonStatus.NORMAL.getType()))
        );

        Integer count = dynamicFollowMapper.selectCount(
                new QueryWrapper<>(
                        new TDynamicFollow()
                                .setDynamicId(dynamic.getId())
                                .setStatus(CommonStatus.NORMAL.getType())
                )
        );

        List<String> imgs = dynamicFileMapper.selectList(
                new LambdaQueryWrapper<TMemberDynamicFile>()
                        .select(TMemberDynamicFile::getUrl)
                        .eq(TMemberDynamicFile::getDynamicId, dynamicId))
                .stream()
                .filter(f -> StringUtils.isNotBlank(f.getUrl()))
                .map(m -> ossConfig.getHostname() + "/" + m.getUrl())
                .collect(Collectors.toList());

        return new DynamicDetailsDTO()
                .setContent(dynamic.getTitle())
                .setDate(DateUtils.parseDateToStr(DateUtils.MM_DD_HH_MM, dynamic.getAddTime()))
                .setFollower(isFollower)
                .setImgs(imgs)
                .setMember(memberShowInfo)
                .setDianzan(dianzan != 0)
                .setCount(count)
                .setId(dynamicId);

    }

    @Override
    public void followComment(String id, String commentId, Integer status) {
        TCommentFollow commentFollow = new TCommentFollow()
                .setCommentId(Long.parseLong(commentId))
                .setStatus(status)
                .setUnLock(id + commentId);
        Integer row = commentFollowMapper.followComment(commentFollow);
    }

    @Override
    public void commentReply(String id, String commentId, String content) {
        TDynamicComment comment = dynamicCommentMapper.selectById(commentId);
        if (comment == null)
            return;
        Long dynamicId = comment.getDynamicId();
        TMemberDynamic dynamic = memberDynamicMapper.selectById(dynamicId);
        if (dynamic == null)
            return;
        if (!id.equals(String.valueOf(dynamic.getMId())))
            throw new ResponseException(403, "只允许作者回复");

        dynamicCommentMapper.updateById(new TDynamicComment().setId(comment.getId()).setReply(content));

    }

    @Override
    public boolean delDynamic(String mId, String id) {
        return memberDynamicMapper.update(null,
                new LambdaUpdateWrapper<TMemberDynamic>()
                        .set(TMemberDynamic::getStatus, CommonStatus.DISABLED.getType())
                        .eq(TMemberDynamic::getId, id)
                        .eq(TMemberDynamic::getMId, mId))
                == 1;
    }
}
